package edu.yngsxy.communityservice.core.wechat;

import cn.hutool.core.util.RandomUtil;
import edu.yngsxy.communityservice.core.config.WechatMpConfig;
import edu.yngsxy.communityservice.core.exception.BusinessException;
import edu.yngsxy.communityservice.core.model.dto.RegisterDTO;
import edu.yngsxy.communityservice.sys.dao.SysUserMapper;
import edu.yngsxy.communityservice.sys.model.entity.SysUser;
import edu.yngsxy.communityservice.sys.service.SysUserService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatusCode;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;

import java.util.Objects;
import java.util.UUID;
import java.util.function.Consumer;

// w微信小程序接口返回结果。使用Java 16+ Record作为DTO，减少模板代码
record WechatLoginResult(Integer errcode, String openid, String session_key, String errmsg) {
}

@Service
@Slf4j
public class WechatService {
    // 注入微信小程序配置
    @Autowired
    private WechatMpConfig wechatConfig;
    @Autowired
    private ObjectMapper objectMapper;//jibson对象映射器
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysUserService sysUsersService;
    @Autowired
    private RestClient.Builder restClientBuilder;
    private RestClient restClient;

    /**
     * 初始化 RestClient
     */
    @PostConstruct
    public void init() {
        // 初始化 RestClient
        this.restClient = restClientBuilder
                .baseUrl("https://api.weixin.qq.com")//微信API地址
                .defaultHeader("Accept", "application/json")
                .build();
    }

    /**
     * 微信登录接口
     * 通过微信小程序code获取用户信息，实现自动登录或注册
     *
     * @param code 微信小程序登录时获取的临时code
     * @return 登录成功的用户信息
     */

    public SysUser login(String code) {
        try {
            // 1. 调用微信API
            String responseBody = restClient.get()
                    .uri("/sns/jscode2session?appid={appid}&secret={secret}&js_code={code}&grant_type=authorization_code",
                            wechatConfig.getAppid(), wechatConfig.getSecret(), code)
                    .retrieve()//获取响应结果
                    .onStatus(HttpStatusCode::isError, // 合并4xx和5xx错误处理
                            (request, response) -> new BusinessException(
                                    "微信接口异常: " + response.getStatusCode() + " " + response.getStatusText()))
                    .body(String.class);
            // 2. 解析响应并使用模式匹配处理结果
            WechatLoginResult result = objectMapper.readValue(responseBody, WechatLoginResult.class);
            // 检查微信接口返回错误
            if (result.errcode() != null && result.errcode() != 0) {
                log.error("微信登录失败: {}", result.errmsg());
                throw new BusinessException("微信登录失败: " + result.errmsg());
            }
            // 3. 查询或注册用户
            SysUser user = sysUserMapper.selectOne(new QueryWrapper<SysUser>().eq("wxmp_openid", result.openid()));
            if (user != null) {
                {//登录成功
                    // 仅在sessionKey变化时更新，减少数据库操作
                    if (!Objects.equals(user.getWxmpSessionKey(), result.session_key())) {
                        user.setWxmpSessionKey(result.session_key());
                        sysUserMapper.updateById(user);
                    }
                    return user;
                }
            }
            //注册
            RegisterDTO ruser = new RegisterDTO();
            ruser.setUsername("wk" + RandomUtil.randomNumbers(18));//设置用户名随机值
            ruser.setPassword(UUID.randomUUID().toString().replace("-", ""));////设置随机密码
            user=sysUsersService.register(ruser, su -> {
                su.setWxmpOpenid(result.openid());//设置微信openid
                su.setWxmpSessionKey(result.session_key());//设置sessionKey
            });
            return user;
        } catch (Exception e) {
            log.error("微信小程序登录失败", e);
            throw new BusinessException("微信小程序登录失败:" + e.getMessage());
        }
    }
}

